\subsubsection{\OptimizingXcodeIV (\ThumbTwoMode)}

По умолчанию Xcode 4.6.3 генерирует код для режима Thumb-2 примерно в такой манере:

\begin{lstlisting}[caption=\OptimizingXcodeIV (\ThumbTwoMode),style=customasmARM]
__text:00002B6C                   _hello_world
__text:00002B6C 80 B5          PUSH            {R7,LR}
__text:00002B6E 41 F2 D8 30    MOVW            R0, #0x13D8
__text:00002B72 6F 46          MOV             R7, SP
__text:00002B74 C0 F2 00 00    MOVT.W          R0, #0
__text:00002B78 78 44          ADD             R0, PC
__text:00002B7A 01 F0 38 EA    BLX             _puts
__text:00002B7E 00 20          MOVS            R0, #0
__text:00002B80 80 BD          POP             {R7,PC}

...

__cstring:00003E70 48 65 6C 6C 6F 20+aHelloWorld  DCB "Hello world!",0xA,0
\end{lstlisting}

% Q: If you subtract 0x13D8 from 0x3E70,
% you actually get a location that is not in this function, or in _puts.
% How is PC-relative addressing done in THUMB2?
% A: it's not Thumb-related. there are just mess with two different segments. TODO: rework this listing.

\myindex{\ThumbTwoMode}
\myindex{ARM!\Instructions!BL}
\myindex{ARM!\Instructions!BLX}
Инструкции \TT{BL} и \TT{BLX} в Thumb, как мы помним, кодируются как пара 16-битных инструкций, 
а в Thumb-2 эти \IT{суррогатные} опкоды расширены так, что новые инструкции кодируются здесь как 
32-битные инструкции.
Это можно заметить по тому что опкоды Thumb-2 инструкций всегда начинаются с \TT{0xFx} либо с \TT{0xEx}.
Но в листинге \IDA байты опкода переставлены местами.
Это из-за того, что в процессоре ARM инструкции кодируются так:
в начале последний байт, потом первый (для Thumb и Thumb-2 режима), либо, 
(для инструкций в режиме ARM) в начале четвертый байт, затем третий, второй и первый 
(т.е. другой \gls{endianness}).

Вот так байты следуют в листингах IDA:

\begin{itemize}
\item для режимов ARM и ARM64: 4-3-2-1;
\item для режима Thumb: 2-1;
\item для пары 16-битных инструкций в режиме Thumb-2: 2-1-4-3.
\end{itemize}

\myindex{ARM!\Instructions!MOVW}
\myindex{ARM!\Instructions!MOVT.W}
\myindex{ARM!\Instructions!BLX}
Так что мы видим здесь что инструкции \TT{MOVW}, \TT{MOVT.W} и \TT{BLX} начинаются с \TT{0xFx}.

Одна из Thumb-2 инструкций это
\TT{MOVW R0, \#0x13D8}~--- она записывает 16-битное число в младшую часть регистра \Reg{0}, очищая старшие биты.

Ещё \TT{MOVT.W R0, \#0}~--- эта инструкция работает так же, как и \TT{MOVT} из предыдущего примера, но она работает в Thumb-2.

\myindex{ARM!переключение режимов}
\myindex{ARM!\Instructions!BLX}
Помимо прочих отличий, здесь используется инструкция \TT{BLX} вместо \TT{BL}.
Отличие в том, что помимо сохранения адреса возврата в регистре \ac{LR} и передаче управления 
в функцию \puts, происходит смена режима процессора с Thumb/Thumb-2 на режим ARM (либо назад).
Здесь это нужно потому, что инструкция, куда ведет переход, выглядит так (она закодирована в режиме ARM):

\begin{lstlisting}[style=customasmARM]
__symbolstub1:00003FEC _puts           ; CODE XREF: _hello_world+E
__symbolstub1:00003FEC 44 F0 9F E5     LDR  PC, =__imp__puts
\end{lstlisting}

Это просто переход на место, где записан адрес \puts в секции импортов.
Итак, внимательный читатель может задать справедливый вопрос: почему бы не вызывать \puts сразу в 
том же месте кода, где он нужен?
Но это не очень выгодно из-за экономии места и вот почему.

\myindex{Динамически подгружаемые библиотеки}
Практически любая программа использует внешние динамические библиотеки (будь то DLL в Windows, .so в *NIX 
либо .dylib в \MacOSX).
В динамических библиотеках находятся часто используемые библиотечные функции, в том числе стандартная функция Си \puts.

\myindex{Relocation}
В исполняемом бинарном файле 
(Windows PE .exe, ELF либо Mach-O) имеется секция импортов, список символов (функций либо глобальных переменных) импортируемых из внешних модулей, а также названия самих модулей.
Загрузчик \ac{OS} загружает необходимые модули и, перебирая импортируемые символы в основном модуле, проставляет правильные адреса каждого символа.
В нашем случае, \IT{\_\_imp\_\_puts} 
это 32-битная переменная, куда загрузчик \ac{OS} запишет правильный адрес этой же функции во внешней библиотеке. 
Так что инструкция \TT{LDR} просто берет 32-битное значение из этой переменной, и, записывая его в регистр \ac{PC}, просто передает туда управление.
Чтобы уменьшить время работы загрузчика \ac{OS}, нужно чтобы ему пришлось записать адрес каждого символа только один раз, в соответствующее, выделенное для них, место.

\myindex{thunk-функции}
К тому же, как мы уже убедились, нельзя одной инструкцией загрузить в регистр 32-битное число без обращений к памяти.
Так что наиболее оптимально выделить отдельную функцию, работающую в режиме ARM, 
чья единственная цель~--- передавать управление дальше, в динамическую библиотеку.
И затем ссылаться на эту короткую функцию из одной инструкции (так называемую \glslink{thunk function}{thunk-функцию}) из Thumb-кода.

\myindex{ARM!\Instructions!BL}
Кстати, в предыдущем примере (скомпилированном для режима ARM), переход при помощи инструкции \TT{BL} ведет 
на такую же \glslink{thunk function}{thunk-функцию}, однако режим процессора не переключается (отсюда отсутствие \q{X} в мнемонике инструкции).

\myparagraph{Еще о thunk-функциях}
\myindex{thunk-функции}

Thunk-функции трудновато понять, скорее всего, из-за путаницы в терминах.
Проще всего представлять их как адаптеры-переходники из одного типа разъемов в другой.
Например, адаптер позволяющее вставить в американскую розетку британскую вилку, или наоборот.
Thunk-функции также иногда называются \IT{wrapper-ами}. \IT{Wrap} в английском языке это \IT{обертывать}, \IT{завертывать}.
Вот еще несколько описаний этих функций:

\begin{framed}
\begin{quotation}
“A piece of coding which provides an address:”, according to P. Z. Ingerman, 
who invented thunks in 1961 as a way of binding actual parameters to their formal 
definitions in Algol-60 procedure calls. If a procedure is called with an expression 
in the place of a formal parameter, the compiler generates a thunk which computes 
the expression and leaves the address of the result in some standard location.

\dots

Microsoft and IBM have both defined, in their Intel-based systems, a “16-bit environment” 
(with bletcherous segment registers and 64K address limits) and a “32-bit environment” 
(with flat addressing and semi-real memory management). The two environments can both be 
running on the same computer and OS (thanks to what is called, in the Microsoft world, 
WOW which stands for Windows On Windows). MS and IBM have both decided that the process 
of getting from 16- to 32-bit and vice versa is called a “thunk”; for Windows 95, 
there is even a tool, THUNK.EXE, called a “thunk compiler”.
\end{quotation}
\end{framed}
% TODO FIXME move to bibliography and quote properly above the quote
( \href{http://go.yurichev.com/17362}{The Jargon File} )

\myindex{LAPACK}
\myindex{FORTRAN}
Еще один пример мы можем найти в библиотеке LAPACK --- (``Linear Algebra PACKage'') написанная на FORTRAN.
Разработчики на \CCpp также хотят использовать LAPACK, но переписывать её на \CCpp, а затем поддерживать несколько версий,
это безумие.
Так что имеются короткие функции на Си вызываемые из \CCpp{}-среды, которые, в свою очередь, вызывают функции на FORTRAN,
и почти ничего больше не делают:

\begin{lstlisting}[style=customc]
double Blas_Dot_Prod(const LaVectorDouble &dx, const LaVectorDouble &dy)
{
    assert(dx.size()==dy.size());
    integer n = dx.size();
    integer incx = dx.inc(), incy = dy.inc();

    return F77NAME(ddot)(&n, &dx(0), &incx, &dy(0), &incy);
}
\end{lstlisting}

Такие ф-ции еще называют ``wrappers'' (т.е., ``обертка'').

